/**********************************************************************
 * SailmiPIM - modular cross-platform feature Personal Information Manager Tools.
 * Copyright(C) 2006-2014  Georg Rudoy
 *
 * Distributed under the Boost Software License, Version 1.0.
 *(See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
 **********************************************************************/

#include "passutils.h"
#include <QString>
#include <QObject>
#include <QInputDialog>
#include <util/xpc/util.h>
#include <sailmipim/structures.h>
#include <sailmipim/core/ientitymanager.h>
#include <sailmipim/core/ipluginsmanager.h>
#include <sailmipim/ipersistentstorageplugin.h>
#include <util/sll/eithercont.h>

namespace SailmiPIM::Util
{
	namespace
	{
		QString GetPasswordHelper(const QByteArray& key, const ICoreProxy_ptr& proxy)
		{
			const auto& result = Util::GetPersistentData(key, proxy);
			if(!result.isValid())
			{
				qWarning() << Q_FUNC_INFO
						<< "invalid result for key"
						<< key;
				return {};
			}

			switch(result.type())
			{
			case QVariant::String:
				return result.toString();
			case QVariant::List:
				return result.toList().value(0).toString();
			case QVariant::StringList:
				return result.toStringList().value(0);
			default:
				qWarning() << Q_FUNC_INFO
						<< "unknown result type"
						<< result.type()
						<< result
						<< "for key"
						<< key;
				return {};
			}
		}
	}

	QString GetPassword(const QString& key, const QString& diaText,
			const ICoreProxy_ptr& proxy, bool useStored)
	{
		if(useStored)
		{
			const auto& result = GetPasswordHelper(key.toUtf8(), proxy);
			if(!result.isNull())
				return result;
		}

		const auto& result = QInputDialog::getText(nullptr,
				QStringLiteral("SailmiPIM"),
				diaText,
				QLineEdit::Password);
		if(!result.isNull())
			SavePassword(result, key, proxy);
		return result;
	}

	void GetPassword(const QString& key, const QString& diaText,
			const ICoreProxy_ptr& proxy,
			const EitherCont<void(), void(QString)>& cont,
			QObject *depender,
			bool useStored)
	{
		if(useStored)
		{
			const auto& result = GetPasswordHelper(key.toUtf8(), proxy);
			if(!result.isNull())
			{
				cont.Right(result);
				return;
			}
		}

		const auto dialog = new QInputDialog;
		dialog->setInputMode(QInputDialog::TextInput);
		dialog->setWindowTitle(QStringLiteral("SailmiPIM"));
		dialog->setLabelText(diaText);
		dialog->setTextEchoMode(QLineEdit::Password);
		dialog->setAttribute(Qt::WA_DeleteOnClose);

		if(depender)
			QObject::connect(depender,
					&QObject::destroyed,
					dialog,
					&QObject::deleteLater);

		QObject::connect(dialog,
				&QDialog::finished,
				[dialog, cont](int r)
				{
					const auto& value = dialog->textValue();
					if(r == QDialog::Rejected || value.isEmpty())
						cont.Left();
					else
						cont.Right(value);
				});

		dialog->show();
	}

	void SavePassword(const QString& password, const QString& key,
			const ICoreProxy_ptr& proxy)
	{
		const auto& plugins = proxy->GetPluginsManager()->GetAllCastableTo<IPersistentStoragePlugin*>();
		for(const auto plugin : plugins)
			if(const auto& storage = plugin->RequestStorage())
				storage->Set(key.toUtf8(), password);
	}
}
